package com.homepig.mongodb;

import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;

import static com.mongodb.client.model.Filters.*;
import static java.util.Arrays.asList;

/**
 * @author homepig
 */
public class QueryStudy {
    public void queryDocuments(MongoCollection collection) {
        FindIterable findIterable = collection.find(and(eq("status", "A"), eq("qty", 25.0), gte("size.h", 14.0)));
        MongoCursor mongoCursor = findIterable.iterator();
        while (mongoCursor.hasNext()) {
            Document obj = (Document) mongoCursor.next();
            System.out.println(obj.toJson());
        }
    }

    public void queryDocuments2(MongoCollection collection) {
        FindIterable findIterable = collection.find(eq("size", Document.parse("{h:14,w:21,uom:'cm'}")));
        MongoCursor mongoCursor = findIterable.iterator();
        while (mongoCursor.hasNext()) {
            Document obj = (Document) mongoCursor.next();
            System.out.println(obj.toJson());
        }
    }

    /**
     * 查询匹配数组
     * to specify equality condition on an array, use the query document eq( <field>, <value>) where <value> is the exact array to match, including the order of the elements.
     * 要在数组上指定相等条件，请使用查询文档eq（<field>，<value>），其中<value>是要匹配的精确数组，包括元素的顺序。
     * The following example queries for all documents where the field tags value is an array with exactly two elements, "red" and "blank", in the specified order:
     * 以下示例将查询字段标记值为具有两个元素（“红色”和“空白”）的数组，并按指定顺序排列的所有文档：
     *
     * @param collection
     */
    public void queryDocument3(MongoCollection collection) {
        FindIterable findIterable = collection.find(eq("tags", asList("blank", "red")));
        MongoCursor mongoCursor = findIterable.iterator();
        while (mongoCursor.hasNext()) {
            Document obj = (Document) mongoCursor.next();
            System.out.println(obj.toJson());
        }
        System.out.println("======================================");
        /*
        If, instead, you wish to find an array that contains both the elements "red" and "blank", without regard to order or other elements in the array, use the $all operator:
        相反，如果您希望查找包含元素“red”和“blank”的数组，而不考虑数组中的顺序或其他元素，请使用$ all运算符：
         */
        findIterable = collection.find(all("tags", asList("blank", "red")));
        mongoCursor = findIterable.iterator();
        while (mongoCursor.hasNext()) {
            Document obj = (Document) mongoCursor.next();
            System.out.println(obj.toJson());
        }
    }

    /**
     * 查询元素的数组
     * To query if the array field contains at least one element with the specified value, use the filter eq( <field>, <value>) where <value> is the element value.
     * 要查询数组字段是否至少包含一个具有指定值的元素，请使用filter eq（<field>，<value>），其中<value>是元素值。
     *
     * @param collection
     */
    public void queryDocument4(MongoCollection collection) {
        /*
        The following example queries for all documents where tags is an array that contains the string "red" as one of its elements:
        以下示例查询所有文档，其中标签是包含字符串“red”的数组作为其元素之一：
         */
        FindIterable findIterable = collection.find(eq("tags", "red"));
        MongoCursor mongoCursor = findIterable.iterator();
        while (mongoCursor.hasNext()) {
            Document obj = (Document) mongoCursor.next();
            System.out.println(obj.toJson());
        }
        System.out.println("==================================");
        /*
        To specify conditions on the elements in the array field, use query operators in the query filter document. For example:
        要指定数组字段中元素的条件，请在查询过滤器文档中使用查询运算符。 例如：

        For example, the following operation queries for all documents where the array dim_cm contains at least one element whose value is greater than 25.
        例如，以下操作查询数组dim_cm至少包含一个值大于或等于21的元素的所有文档。
         */
        findIterable = collection.find(gte("dim_cm", 21));
        mongoCursor = findIterable.iterator();
        while (mongoCursor.hasNext()) {
            Document obj = (Document) mongoCursor.next();
            System.out.println(obj.toJson());
        }
    }

    /**
     * 为数组元素指定多个条件
     * <p>
     * When specifying compound conditions on array elements, you can specify the query such that either a single array element meets these condition or any combination of array elements meets the conditions.
     * 当在数组元素上指定复合条件时，可以指定查询，使得单个数组元素满足这些条件或数组元素的任意组合满足条件。
     * <p>
     * Query an Array with Compound Filter Conditions on the Array Elements
     * 在数组元素上查询包含复合过滤条件的数组
     * <p>
     * The following example queries for documents where the dim_cm array contains elements that in some combination satisfy the query conditions;
     * e.g., one element can satisfy the greater than 15 condition and another element can satisfy the less than 20 condition, or a single element can satisfy both:
     * 以下示例将查询dim_cm数组中包含的元素在某些组合中是否满足查询条件的文档;
     * 例如，一个元素可以满足大于15的条件，另一个元素可以满足小于20的条件，或者单个元素可以满足以下两者：
     *
     * @param collection
     */
    public void queryDocument5(MongoCollection collection) {
        FindIterable findIterable = collection.find(and(gt("dim_cm", 15), lt("dim_cm", 20)));
        MongoCursor mongoCursor = findIterable.iterator();
        while (mongoCursor.hasNext()) {
            Document obj = (Document) mongoCursor.next();
            System.out.println(obj.toJson());
        }
    }
    /**
     * Query for an Array Element that Meets Multiple Criteria
     * 查询符合多个条件的数组元素
     * <p>
     * Use $elemMatch operator to specify multiple criteria on the elements of an array such that at least one array element satisfies all the specified criteria.
     * 使用$ elemMatch操作符在数组的元素上指定多个条件，使至少一个数组元素满足所有指定的条件。
     * <p>
     * The following example queries for documents where the dim_cm array contains at least one element that is both greater than ($gt) 22 and less than ($lt) 30:
     * 以下示例查询dim_cm数组包含至少一个大于（$ gt）22且小于（$ lt）30的元素的文档：
     * @param collection
     */
    public void queryDocument6(MongoCollection collection) {
        FindIterable findIterable = collection.find(elemMatch("dim_cm", Document.parse("{$gt:15,$lt:20}")));
        MongoCursor mongoCursor = findIterable.iterator();
        while (mongoCursor.hasNext()) {
            Document obj = (Document) mongoCursor.next();
            System.out.println(obj.toJson());
        }
    }

    /**
     * 按数组索引位置查询元素
     * Using dot notation, you can specify query conditions for an element at a particular index or position of the array. The array uses zero-based indexing.
     * 使用点符号，您可以为特定索引或数组位置的元素指定查询条件。 该数组使用从零开始的索引。
     * <p>
     * The following example queries for all documents where the second element in the array dim_cm is greater than 25:
     * 以下示例查询数组dim_cm中第二个元素大于25的所有文档：
     *
     * @param collection
     */
    public void queryDocument7(MongoCollection collection) {
        // 当使用点符号查询时，字段和嵌套字段必须在引号内。
        FindIterable findIterable = collection.find(gt("dim_cm.1", 25));
        MongoCursor mongoCursor = findIterable.iterator();
        while (mongoCursor.hasNext()) {
            Document obj = (Document) mongoCursor.next();
            System.out.println(obj.toJson());
        }
    }

    /**
     * 按数组长度查询数组
     *
     * @param collection
     */
    public void queryDocument8(MongoCollection collection) {
        FindIterable findIterable = collection.find(size("tags", 3));
        MongoCursor mongoCursor = findIterable.iterator();
        while (mongoCursor.hasNext()) {
            Document obj = (Document) mongoCursor.next();
            System.out.println(obj.toJson());
        }
    }

    public static void main(String[] args) {
        MongoClient client = new MongoClient("localhost", 27017);
        MongoDatabase database = client.getDatabase("mongo_stu");
        MongoCollection collection = database.getCollection("inventory");

        QueryStudy queryStudy = new QueryStudy();
        // queryStudy.queryDocuments(collection);
        // queryStudy.queryDocuments2(collection);
        // queryStudy.queryDocument3(collection);
        // queryStudy.queryDocument4(collection);
        // queryStudy.queryDocument5(collection);
        System.out.println("==================");
        // queryStudy.queryDocument6(collection);
        // queryStudy.queryDocument7(collection);
        queryStudy.queryDocument8(collection);
    }
}
